﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FXnaInfrastructure;

namespace GWModflow.FileLayers.MT3DMS
{
    /// <summary>
    /// 对流子程序包
    /// </summary>
   public class AdvectionPack:Package 
    {
       public AdvectionPack()
       {
           this._fileType = FileType.ADV;
           this.Fname = "mt3dms.adv";
       }

        private int _MIXELM; //一个对流求解功能的整数标识。=0，标准有限差分法和上游或空间中央的权重取决于NADVFD值,	=1，特点的前瞻性跟踪法（MOC）,	=2，特点的反向跟踪修正法（MMOC）,=3，特点的混合法（HMOC），其中MOC或MMOC被自动的动态选择	=-1，第三级TVD方案（ULTIMATE）。
       /// <summary>
        /// 一个对流求解功能的整数标识。
        /// =0，标准有限差分法和上游或空间中央的权重取决于NADVFD值,
        /// =1，特点的前瞻性跟踪法（MOC）,
        /// =2，特点的反向跟踪修正法（MMOC）
        /// =3，特点的混合法（HMOC），其中MOC或MMOC被自动的动态选择
        /// =-1，第三级TVD方案（ULTIMATE）
       /// </summary>
        public int MIXELM
        {
            get { return _MIXELM; }
            set { _MIXELM = value; }
        }
        private double _PERCEL;//在一个运移步内任何方向所允许的柯朗数（即单元数或一个单元的分数）对流 
       /// <summary>
        /// 在一个运移步内任何方向所允许的柯朗数（即单元数或一个单元的分数）对流 
       /// </summary>
        public double PERCEL
        {
            get { return _PERCEL; }
            set { _PERCEL = value; }
        }

        private int _MXPART;//被允许的活动颗粒的最大总数，并只有在MIXELM=1或3的时候使用
       /// <summary>
        /// 被允许的活动颗粒的最大总数，并只有在MIXELM=1或3的时候使用
       /// </summary>
        public int MXPART
        {
            get { return _MXPART; }
            set { _MXPART = value; }
        }

        private int _NADVFD;//一个标示哪一个权重方案将被使用的整数标识；只有当对流项通过隐式有限分差法求解的时候使用
       /// <summary>
        /// 一个标示哪一个权重方案将被使用的整数标识；只有当对流项通过隐式有限分差法求解的时候使用
        /// NADVFD=0或1，使用上游权重（默认）
        /// =2，使用空间中央权重
       /// </summary>
        public int NADVFD
        {
            get { return _NADVFD; }
            set { _NADVFD = value; }
        }

        private int _ITRACK;//一个标示哪一个颗粒跟踪算法在欧拉-拉格朗日方法中使用的标识
       /// <summary>
        /// ITRACK=1， 使用一阶Euler算法。
        /// =2，使用四阶Runge-Kutta算法；此功能要求计算，并且只在PERCEL被设置大于1时使用。
        /// =3，混合使用一阶和四阶算法；Runge-Kutta算法在源汇单元以及其相邻单元中使用，而Euler算法在其他地方使用
       /// </summary>
        public int ITRACK
        {
            get { return _ITRACK; }
            set { _ITRACK = value; }
        }
        private double _WD=0.5;//一个0.5和1之间的浓度权重因子。它用于帮助算子在基于颗粒跟踪的方法上分裂。一个0.5的数值是一般适用的。WD值可以调适以便取得更好的衡。一般来说，当对流越加主导时，它的值可以向1增长。

       /// <summary>
        /// 一个0.5和1之间的浓度权重因子。它用于帮助算子在基于颗粒跟踪的方法上分裂。
        /// 一个0.5的数值是一般适用的。WD值可以调适以便取得更好的衡。
        /// 一般来说，当对流越加主导时，它的值可以向1增长。
       /// </summary>
        public double WD
        {
            get { return _WD; }
            set { _WD = value; }
        }

        private double _DCEPS;//一个小的相对单元浓度梯度，当梯度小于DCEPS值，对流运移可以忽略不计。一个10-5左右的数值是一般适用的。
       /// <summary>
        /// 一个小的相对单元浓度梯度，当梯度小于DCEPS值，对流运移可以忽略不计。
        /// 一个10^-5左右的数值是一般适用的。
       /// </summary>
        public double DCEPS
        {
            get { return _DCEPS; }
            set { _DCEPS = value; }
        }

        private int _NPLANE;//一个标示是否以随机或固定模式来选择移动颗粒的初始位置的标识
       /// <summary>
        /// 一个标示是否以随机或固定模式来选择移动颗粒的初始位置的标识
        /// =0，选用随机模式来决定初始位置
        /// >0，选用固定模式来决定初始位置
        /// 对于平视的二维模拟，将NPLANE设置为1
        /// 对于横断面或三维模拟，NPLANE=2比较适合
        /// 如果需要竖直方向更多的解，适当提高NPLANE值
       /// </summary>
        public int NPLANE
        {
            get { return _NPLANE; }
            set { _NPLANE = value; }
        }

        private int _NPL;//相对单元浓度梯度小于或等于DCEPS的单元中每单元初始颗粒的数量
       /// <summary>
        /// 相对单元浓度梯度小于或等于DCEPS的单元中每单元初始颗粒的数量
       /// </summary>
        public int NPL
        {
            get { return _NPL; }
            set { _NPL = value; }
        }
        private int _NPH;//相对单元浓度大于DCEPS的单元中每单元初始颗粒的数量。NPH的选择取决于流场的特性和电脑内存的限制
       /// <summary>
        /// 相对单元浓度大于DCEPS的单元中每单元初始颗粒的数量。
        /// NPH的选择取决于流场的特性和电脑内存的限制
       /// </summary>
        public int NPH
        {
            get { return _NPH; }
            set { _NPH = value; }
        }
        private int _NPMIN;//是每个单元中允许的最小颗粒数
       /// <summary>
        /// 是每个单元中允许的最小颗粒数,一般来说一个在0和4之间的数是适宜的
       /// </summary>
        public int NPMIN
        {
            get { return _NPMIN; }
            set { _NPMIN = value; }
        }
        private int _NPMAX;//每个单元中允许的最大颗粒数,一般来说NPMAX可以被设为NPH的两倍
       /// <summary>
        /// 每个单元中允许的最大颗粒数,一般来说NPMAX可以被设为NPH的两倍
       /// </summary>
        public int NPMAX
        {
            get { return _NPMAX; }
            set { _NPMAX = value; }
        }

        private int _INTERP;//一个标识，表示在MMOC方案中使用的浓度内插法。现在只有使用线性内插法。输入INTERP=1
       /// <summary>
        /// 一个标识，表示在MMOC方案中使用的浓度内插法。现在只有使用线性内插法。输入INTERP=1
       /// </summary>
        public int INTERP
        {
            get { return _INTERP; }
            set { _INTERP = value; }
        }
        private int _NLSINK;//一个标识，表示颗粒的初始位置是否选用随机或固定模式在MMOC方案中估算源单元。惯例是与NPLANE一样。一般将NLSINK设为与NPLANE一样是适宜的。
       /// <summary>
        /// 一个标识，表示颗粒的初始位置是否选用随机或固定模式在MMOC方案中估算源单元。
        /// 惯例是与NPLANE一样。一般将NLSINK设为与NPLANE一样是适宜的。
       /// </summary>
        public int NLSINK
        {
            get { return _NLSINK; }
            set { _NLSINK = value; }
        }
        private int _NPSINK;//在MMOC方案中用来估算源单元的的颗粒数。惯例是与NPH一样。一般将NPSINK设为与NPH一样是适宜的
       /// <summary>
        /// 在MMOC方案中用来估算源单元的的颗粒数。
        /// 惯例是与NPH一样。一般将NPSINK设为与NPH一样是适宜的
       /// </summary>
        public int NPSINK
        {
            get { return _NPSINK; }
            set { _NPSINK = value; }
        }
        private double _DCHMOC;//关键相对浓度坡度用来在HMOC解决方案控制选用MOC或MMOC
       /// <summary>
        /// 关键相对浓度坡度用来在HMOC解决方案控制选用MOC或MMOC
        /// 在相对浓度坡度大于DCHMOC的单元选用MOC解法
        /// 在相对浓度坡度小于或等于DCHMOC的单元选用MMOC解法
       /// </summary>
        public double DCHMOC
        {
            get { return _DCHMOC; }
            set { _DCHMOC = value; }
        }

        public override void WriteFile(string path)
        {
            string content = string.Format("{0,10}", GetNumberLengthFormat ( this.MIXELM,10))  + string.Format("{0,10}", GetNumberLengthFormat (  this.PERCEL,10));
            if (this.MIXELM == 1 || this.MIXELM == 3)
            {
                content += string.Format("{0,10}", GetNumberLengthFormat (this.MXPART,10));
            }
            if (this.MIXELM == 0)
            {
                content += string.Format("{0,10}",GetNumberLengthFormat ( this.NADVFD,10));
            }
            content += "              MIXELM,PERCEL" + "\r\n";

            if (this.MIXELM == 1 || this.MIXELM == 2 || this.MIXELM == 3)
            {
                content += string.Format("{0,10}", GetNumberLengthFormat (this.ITRACK,10)) + string.Format("{0,10}", GetNumberLengthFormat (this.WD,10)) + "              ITRACK,WD" + "\r\n";
            }
            if (this.MIXELM == 1 || this.MIXELM == 3)
            {
                content += string.Format("{0,10}",GetNumberLengthFormat ( this.DCEPS,10)) + string.Format("{0,10}",GetNumberLengthFormat ( this.NPLANE,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.NPL,10))  +
                    string.Format("{0,10}",GetNumberLengthFormat ( this.NPH,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.NPMIN,10))  + string.Format("{0,10}",GetNumberLengthFormat ( this.NPMAX,10)) + "              DCEPS,NPLANE,NPL,NPH,NPMIN,NPMAX" + "\r\n";
            }
            if (this.MIXELM == 2 || this.MIXELM == 3)
            {
                content += string.Format("{0,10}", GetNumberLengthFormat (this.INTERP,10))  + string.Format("{0,10}", GetNumberLengthFormat (this.NLSINK,10)) + string.Format("{0,10}",GetNumberLengthFormat ( this.NPSINK,10)) + "              INTERP,NLSINK,NPSINK" + "\r\n";
            }
            if (this.MIXELM == 3)
            {
                content += string.Format("{0,10}",GetNumberLengthFormat ( this.DCHMOC,10)) + "              DCHMOC" + "\r\n";
            }


            string fname = path + this.Fname;
            FileHelper.WriteFile(fname, content);
           
        }
   }
}
